/**
 * @file dial.h
 *
 */
#ifndef DIAL_H
#define DIAL_H

#ifdef __cplusplus
extern "C" {
#endif

/*********************
 *      INCLUDES
 *********************/

#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lvgl.h"
#include "lv_watch_conf.h"
#else
#include "../../../lvgl/lvgl.h"
#include "../../../lv_watch_conf.h"
#endif

#if USE_LV_WATCH_DIAL != 0

/*********************
 *      DEFINES
 *********************/
#if LV_WATCH_SIMULATOR_360 != 0
#define WATCH_DIAL_BUILDIN_LIST_FILE "R:/png/dial/buildin_dial_list_360.db"
#define WATCH_DIAL_BUILDIN_AM_LIST_FILE "R:/png/dial/buildin_dial_am_list_360.db"
#else
#define WATCH_DIAL_BUILDIN_LIST_FILE "R:/png/dial/buildin_dial_list.db"
#define WATCH_DIAL_BUILDIN_AM_LIST_FILE "R:/png/dial/buildin_dial_am_list.db"
#endif
#define WATCH_DIAL_EXT_AM_LIST_FILE "C:/ext_dial_am_list.db"
#define WATCH_DIAL_EXT_LIST_FILE "C:/ext_dial_list.db"
#define WATCH_DIAL_MAX_LINE_LEN 200
#define WATCH_MAX_PATH_LEN 80
#define WATCH_MAX_DIAL_NAME_LEN 20
#define DIAL_MAX_JSON_FILE_CNT  2

#define DIAL_PATH_MAX    260
#define DIAL_FILE_DIR    0x10    /* Directory */
#define DIAL_FILE_ARC    0x20    /* Archive, normal file */

#define PRESSURE_LEVEL_HIGH       80
#define PRESSURE_LEVEL_MEDIUM     60
#define PRESSURE_LEVEL_LOW        40

#define DIAL_DEBUG                0
#define DIAL_USE_CANVAS           1
/**********************
 *      TYPEDEFS
 **********************/
typedef uint8_t watch_dial_type_t;

enum {
    ELEMENT_TYPE_INVILID = 0,
    ELEMENT_TYPE_TIME_DIGIT,        //1
    ELEMENT_TYPE_TIME_HAND,         //2
    ELEMENT_TYPE_AM_PM,             //3
    ELEMENT_TYPE_WEEK,              //4
    ELEMENT_TYPE_DATE,              //5
    ELEMENT_TYPE_WEATHER,           //6
    ELEMENT_TYPE_CALORIE,           //7
    ELEMENT_TYPE_STEP,              //8
    ELEMENT_TYPE_DISTANCE,          //9
    ELEMENT_TYPE_BATTERY,           //10
    ELEMENT_TYPE_SLEEP_QUALITY,     //11
    ELEMENT_TYPE_PRESSURE,          //12
    ELEMENT_TYPE_HEART_RATE,        //13
    ELEMENT_TYPE_BLOOD_OXYGEN,      //14
    ELEMENT_TYPE_BG_SWITCH,         //15  /*except when updating all elements, always at the last*/
    ELEMENT_TYPE_MAX
};
typedef uint8_t watch_element_type_t;

enum {
    IMG_TYPE_TIME_HOUR_TENS = ELEMENT_TYPE_TIME_DIGIT * 10,//10
    IMG_TYPE_TIME_HOUR_UNIT,        //11
    IMG_TYPE_TIME_MIN_TENS,         //12
    IMG_TYPE_TIME_MIN_UNIT,         //13
    IMG_TYPE_TIME_SEC_TENS,         //14
    IMG_TYPE_TIME_SEC_UNIT,         //15
    IMG_TYPE_TIME_CONNECTOR,        //16

    IMG_TYPE_TIME_HOUR_HAND = ELEMENT_TYPE_TIME_HAND * 10,//20
    IMG_TYPE_TIME_MIN_HAND,              //21
    IMG_TYPE_TIME_SEC_HAND,              //22
    IMG_TYPE_TIME_CENTER_DOT,            //23

    IMG_TYPE_TIME_AM_PM = ELEMENT_TYPE_AM_PM * 10,//30

    IMG_TYPE_WEEK_DIGIT = ELEMENT_TYPE_WEEK * 10, //40
    IMG_TYPE_WEEK_HAND,             //41

    IMG_TYPE_YEAR_THOUSAND = ELEMENT_TYPE_DATE * 10,//50
    IMG_TYPE_YEAR_HUNDRED,          //51
    IMG_TYPE_YEAR_TENS,             //52
    IMG_TYPE_YEAR_UNIT,             //53
    IMG_TYPE_MON_TENS,              //54
    IMG_TYPE_MON_UNIT,              //55
    IMG_TYPE_DAY_TENS,              //56
    IMG_TYPE_DAY_UNIT,              //57
    IMG_TYPE_MON,                   //58
    IMG_TYPE_DATE_CONNECTOR,        //59

    IMG_TYPE_WEATHER = ELEMENT_TYPE_WEATHER * 10,//60
    IMG_TYPE_TEMPERATURE_TENS,      //61
    IMG_TYPE_TEMPERATURE_UNIT,      //62
    IMG_TYPE_TEMPERATURE_MINUS,     //63
    IMG_TYPE_TEMPERATURE_CENT,      //64
    IMG_TYPE_WEATHER_UV,            //65
    IMG_TYPE_WEATHER_AQI,           //66

    IMG_TYPE_CALORIE = ELEMENT_TYPE_CALORIE * 10, //70
    IMG_TYPE_CALORIE_HUNDRED,       //71
    IMG_TYPE_CALORIE_TENS,          //72
    IMG_TYPE_CALORIE_UNIT,          //73
    IMG_TYPE_CALORIE_KCAL,          //74
    IMG_TYPE_CALORIE_PROGRESS,      //75

    IMG_TYPE_STEP = ELEMENT_TYPE_STEP * 10,       //80
    IMG_TYPE_STEP_MYRI,             //81
    IMG_TYPE_STEP_THOUSAND,         //82
    IMG_TYPE_STEP_HUNDRED,          //83
    IMG_TYPE_STEP_TENS,             //84
    IMG_TYPE_STEP_UNIT,             //85
    IMG_TYPE_STEP_STEP,             //86
    IMG_TYPE_STEP_PROGRESS,         //87

    IMG_TYPE_DISTANCE = ELEMENT_TYPE_DISTANCE * 10,//90
    IMG_TYPE_DISTANCE_TENS,         //91
    IMG_TYPE_DISTANCE_UNIT,         //92
    IMG_TYPE_DISTANCE_DOT,          //93
    IMG_TYPE_DISTANCE_DECI,         //94
    IMG_TYPE_DISTANCE_KM,           //95
    IMG_TYPE_DISTANCE_PROGRESS,     //96

    IMG_TYPE_BATTERY = ELEMENT_TYPE_BATTERY * 10,  //100
    IMG_TYPE_BATTERY_HUNDRED,       //101
    IMG_TYPE_BATTERY_TENS,          //102
    IMG_TYPE_BATTERY_UNIT,          //103
    IMG_TYPE_BATTERY_PERCENT,       //104
    IMG_TYPE_BATTERY_SIGN,          //105

    IMG_TYPE_SLEEP_QUALITY = ELEMENT_TYPE_SLEEP_QUALITY * 10,//110
    IMG_TYPE_SLEEP_QUALITY_VALUE,//111

    IMG_TYPE_PRESSURE = ELEMENT_TYPE_PRESSURE * 10,         //120
    IMG_TYPE_PRESSURE_HUNDRED,      //121
    IMG_TYPE_PRESSURE_TENS,         //122
    IMG_TYPE_PRESSURE_UNIT,         //123
    IMG_TYPE_PRESSURE_KPA,          //124
    IMG_TYPE_PRESSURE_LEVEL,        //125

    IMG_TYPE_HEART_RATE = ELEMENT_TYPE_HEART_RATE * 10,      //130
    IMG_TYPE_HEART_RATE_HUNDRED,    //131
    IMG_TYPE_HEART_RATE_TENS,       //132
    IMG_TYPE_HEART_RATE_UNIT,       //133
    IMG_TYPE_HEART_RATE_BPM,        //134

    IMG_TYPE_BLOOD_OXYGEN = ELEMENT_TYPE_BLOOD_OXYGEN * 10,  //140
    IMG_TYPE_BLOOD_OXYGEN_TENS,     //141
    IMG_TYPE_BLOOD_OXYGEN_UNIT,     //142
    IMG_TYPE_BLOOD_OXYGEN_PERCENT,  //143

    IMG_TYPE_BG = ELEMENT_TYPE_BG_SWITCH * 10, //150
};
typedef uint8_t watch_img_type_t;

enum {
    LABEL_TYPE_TIME_HOUR= 0,        //0
    LABEL_TYPE_TIME_MIN,            //1
    LABEL_TYPE_TIME_SEC,            //2
    LABEL_TYPE_TIME_CONNECTOR,      //3 ":" "/"
    LABEL_TYPE_AM_PM,               //4
    LABEL_TYPE_WEEK,                //5  周一/Mon
    LABEL_TYPE_WEEK_EN,             //6  Mon
    LABEL_TYPE_DATE_YEAR,           //7
    LABEL_TYPE_DATE_MONTH,          //8  "01 02 ... 12"
    LABEL_TYPE_DATE_DAY,            //9
    LABEL_TYPE_DATE_CONNECTOR,      //10 ";" "/" "年" "月" "日"
    LABEL_TYPE_MONTH,               //11 "Jan Feb ... Dec"
    LABEL_TYPE_WEATHER_TEMP,        //12
    LABEL_TYPE_WEATHER_UV,          //13
    LABEL_TYPE_WEATHER_AQI,         //14
    LABEL_TYPE_CALORIE,             //15
    LABEL_TYPE_CALORIE_KCAL,        //16
    LABEL_TYPE_STEP,                //17
    LABEL_TYPE_STEP_STEPS,          //18
    LABEL_TYPE_DISTANCE,            //19
    LABEL_TYPE_DISTANCE_KM,         //20
    LABEL_TYPE_BATTERY,             //21
    LABEL_TYPE_SLEEP_QUALITY,       //22
    LABEL_TYPE_PRESSURE,            //23
    LABEL_TYPE_HEART_RATE,          //24
    LABEL_TYPE_HEART_RATE_BPM,      //25
    LABEL_TYPE_BLOOD_OXYGEN,        //26

};
typedef uint8_t watch_label_type_t;

enum {
    BAR_TYPE_INVALID = 0,
    BAR_TYPE_CIRCLE,
    BAR_TYPE_RECT
};
typedef uint8_t watch_bar_type_t;

typedef struct
{
    uint8_t sub_img_cnt;
    lv_ll_t sub_img_ll; //sub img list, char img[WATCH_MAX_PATH_LEN]
} watch_element_subimg_dsc_t;

typedef struct
{
    uint8_t img_type;//watch_img_type_t
    lv_point_t img_pos;
    watch_element_subimg_dsc_t * subimg;
    lv_obj_t * img_obj;
} watch_element_img_dsc_t;

typedef struct
{
    uint8_t label_type; //watch_label_type_t
    char * text;
    lv_color_t text_color;
    lv_point_t text_pos;
    uint8_t font_size;
    char ttf_file[WATCH_MAX_PATH_LEN];
    lv_font_t * label_font;
    lv_obj_t * label_obj;
} watch_element_label_dsc_t;

typedef struct
{
    uint8_t bar_type;//0 means no bar; watch_element_bar_type_t
    lv_point_t bar_pos;
    lv_color_t bar_color;
    uint8_t bar_w;
    uint8_t bar_h;
    lv_obj_t * bar_obj;
} watch_element_bar_dsc_t;

typedef struct
{
    uint8_t element_type;
    char element_name[WATCH_MAX_DIAL_NAME_LEN];
    char element_pre_img[WATCH_MAX_PATH_LEN];
    uint8_t img_cnt; //0 means no img
    lv_ll_t img_ll; //watch_element_img_dsc_t;
    uint8_t label_cnt;
    lv_ll_t label_ll;
    watch_element_bar_dsc_t bar_dsc;
} watch_element_base_t;

typedef struct
{
    lv_point_t element_pos;
    uint8_t element_cnt;
    uint8_t act_type; // 当前显示的element  watch_element_type_t;
    uint8_t layer; // 0--bottom
    lv_ll_t element_dsc_ll; //watch_element_base_t *
} watch_element_t;

typedef struct
{
    char name[WATCH_MAX_DIAL_NAME_LEN];
    char preview_img[WATCH_MAX_PATH_LEN];
    char bg_img[WATCH_MAX_PATH_LEN];
    uint8_t configurable; //0-unconfigurable 1-configurable 2-psm
    lv_ll_t element_ll; //watch_element_t
} watch_dial_t;

typedef struct
{
    lv_cont_ext_t old_ext;
    watch_dial_t * watch_dial;
#if DIAL_USE_CANVAS != 0
    lv_obj_t *    canvas;
#endif
    uint8_t       hour;
    uint8_t       min;
    uint8_t       sec;
    uint8_t       configuring;
} lv_clock_ext_t;

typedef struct
{
    char json_file[DIAL_MAX_JSON_FILE_CNT][WATCH_MAX_PATH_LEN];
    uint8_t json_file_cnt;
} watch_dial_conf_path_t;

/**********************
 * GLOBAL PROTOTYPES
 **********************/

/**
 * Create a dial application
 */
lv_obj_t * dial_create(lv_obj_t * tabview, lv_obj_t * ancient_tab, uint8_t index);
void dial_clock_start_update(lv_obj_t *clock_cont);
void dial_update_digital_display(void *ptr);
void dial_clock_update_immediately(void);
void dial_destroy(void);
bool dial_del_dial(char * name, uint8_t ambient);
void dial_add_new_dial(char * zip_path);
watch_dial_conf_path_t * dial_unzip(const char * zip_file_name);
void dial_parse(const char * cfg_file_name, watch_dial_t * dial);

lv_obj_t * dial_add_bg_img(lv_obj_t * par, watch_dial_t * watch_dial);
bool dial_add_element(lv_obj_t * par, watch_dial_t * watch_dial);
void dial_update_element(watch_dial_t * watch_dial, watch_element_type_t type);
lv_obj_t * dial_get_clock_cont(void);
void dial_get_dsc_file(uint8_t dial_type, uint8_t psm, char * dsc_file_name);
void dial_init_act_element(watch_dial_t * watch_dial);
void dial_add_configurable_element(lv_obj_t * par);
bool dial_switch_to_ambient(void);
void dial_start_app(lv_point_t * point);
void dial_free_element(watch_dial_t * dial);
void dial_ambient_destroy(lv_obj_t * activity_obj);
watch_dial_type_t dial_read_type(uint8_t ambient);
void dial_write_type(watch_dial_type_t cur_type, uint8_t ambient);
void dial_ambient_update(void);
void dial_poweroff(void);
void dial_clock_stop_update(void);
void dial_clock_resume_task(void);
uint8_t dial_get_config_state(void);
void dial_update_second(uint8_t sec, watch_dial_t * watch_dial);
void dial_set_cont_null(void);
void dial_update_all_element(lv_obj_t * clock_cont);
void dial_reset_bg_index(void);
#if DIAL_USE_CANVAS != 0
void dial_clean_canvas(bool switch_bg);
#endif
//for test
void dial_test(void);
/**********************
 *      MACROS
 **********************/

#endif /*USE_LV_WATCH_DIAL*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /*DIAL_H*/
